home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 526-550 / disk_535 / keymacro / keymacro-handler.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  19KB  |  919 lines

  1. /****************************************************************************
  2. *
  3. *    KeyMacro-Handler.c ----    KeyMacro handler.
  4. *
  5. *    Author ----------------    Olaf Barthel, MXM
  6. *                Brabeckstrasse 35
  7. *                D-3000 Hannover 71
  8. *
  9. *    KeyMacro  ©  Copyright  1990  by  MXM;  Executable  program,
  10. *    documentation  and  source  code are shareware.  If you like
  11. *    this  program  a  small donation will entitle you to receive
  12. *    updates and new programs from MXM.
  13. *
  14. ****************************************************************************/
  15.  
  16.     /* Function prototypes. */
  17.  
  18. struct Process *            CreateFuncProc(UBYTE *Name,LONG Priority,APTR InitCode,ULONG StackSize);
  19. VOID                    FreeString(BPTR Byte);
  20. BPTR                    CreateBSTR(UBYTE *s);
  21. BPTR                    CopyPath(VOID);
  22. VOID                    FakeCLI(VOID);
  23. VOID                    ClearPath(BPTR InitPath);
  24. VOID                    StopFakery(VOID);
  25. VOID *                    DeleteMacroMsg(struct MacroMessage *scm_Msg);
  26. VOID __saveds                Executor(VOID);
  27. struct MacroKey *            FindMacroKey(LONG Code,LONG Qualifier);
  28. struct InputEvent * __asm __saveds    EventHandler(register __a0 struct InputEvent *Event);
  29. BYTE                    OpenAll(VOID);
  30. VOID                    CloseAll(VOID);
  31. BYTE                    UStrCmp(UBYTE *a,UBYTE *b);
  32.  
  33. VOID *                    AllocRem(LONG ByteSize,LONG Requirements);
  34. VOID *                    FreeRem(LONG *MemoryBlock);
  35. VOID *                    SendMacroMsg(struct MacroMessage *scm_Msg,struct MsgPort *scm_Port);
  36. ULONG                    KeyInvert(UBYTE AnsiKey,struct InputEvent *Event,struct KeyMap *KeyMap,BYTE Depth);
  37.  
  38. LONG __saveds                Main(VOID);
  39.  
  40.     /* Shared library identifiers. */
  41.  
  42. extern struct ExecBase    *SysBase;
  43. struct IntuitionBase    *IntuitionBase;
  44. struct Library        *LayersBase;
  45.  
  46.     /* Global handshake data. */
  47.  
  48. struct MSeg        *MSeg;
  49.  
  50.     /* Process<->Process communication data. */
  51.  
  52. struct Process        *ExecuteProc;
  53. struct MsgPort        *ExecutePort;
  54.  
  55.     /* Input device data. */
  56.  
  57. struct MsgPort        *InputDevPort;
  58. struct IOStdReq        *InputRequestBlock;
  59. struct Interrupt    *InputHandler;
  60. struct InputEvent    *FakeInputEvent;
  61.  
  62.     /* Console device data. */
  63.  
  64. struct IOStdReq        *ConsoleRequest;
  65. struct MsgPort        *ConsolePort;
  66.  
  67.     /* Timer device data. */
  68.  
  69. struct timerequest    *TimeRequest;
  70. struct MsgPort        *TimePort;
  71.  
  72. BYTE             SigBit = -1;
  73.  
  74. struct ExecBase        *SysBase;
  75. struct DosLibrary    *DOSBase;
  76.  
  77.     /* Main():
  78.      *
  79.      *    This is the entry point to the handler process.
  80.      */
  81.  
  82. LONG __saveds
  83. Main()
  84. {
  85.     struct Process        *ThatsMe;
  86.     ULONG             SignalSet;
  87.     struct MacroMessage    *MacroMsg;
  88.     LONG             i;
  89.  
  90.     SysBase = *(struct ExecBase **)4;
  91.  
  92.         /* Do I know myself? */
  93.  
  94.     ThatsMe = (struct Process *)SysBase -> ThisTask;
  95.  
  96.         /* Don't let anybody call us from CLI. */
  97.  
  98.     if(ThatsMe -> pr_CLI)
  99.         goto Quit;
  100.  
  101.         /* Can we find the global MsgPort? */
  102.  
  103.     if(!(MSeg = (struct MSeg *)FindPort(PORTNAME)))
  104.     {
  105.         Forbid();
  106.  
  107.         Signal(MSeg -> Father,MSeg -> RingBack);
  108.  
  109.         goto Quit;
  110.     }
  111.  
  112.         /* This older revision probably doesn't support
  113.          * some newer structure tags -> exit.
  114.          */
  115.  
  116.     if(MSeg -> Revision < REVISION)
  117.     {
  118.         Forbid();
  119.  
  120.         Signal(MSeg -> Father,MSeg -> RingBack);
  121.  
  122.         goto Quit;
  123.     }
  124.  
  125.         /* The MsgPort is already owned by someone
  126.          * else.
  127.          */
  128.  
  129.     if(MSeg -> Port . mp_Flags & PA_SIGNAL)
  130.     {
  131.         Forbid();
  132.  
  133.         Signal(MSeg -> Father,MSeg -> RingBack);
  134.  
  135.         goto Quit;
  136.     }
  137.  
  138.         /* Open the libraries. */
  139.  
  140.     if(!OpenAll())
  141.     {
  142.         CloseAll();
  143.  
  144.         Forbid();
  145.  
  146.         Signal(MSeg -> Father,MSeg -> RingBack);
  147.  
  148.         goto Quit;
  149.     }
  150.  
  151.         /* Start the executing process. */
  152.  
  153.     MSeg -> Child = (struct Task *)ThatsMe;
  154.  
  155.     if(!(ExecuteProc = (struct Process *)CreateFuncProc("KeyMacro CLI",10,Executor,4000)))
  156.     {
  157.         CloseAll();
  158.  
  159.         Forbid();
  160.  
  161.         MSeg -> Child = NULL;
  162.         Signal(MSeg -> Father,MSeg -> RingBack);
  163.  
  164.         goto Quit;
  165.     }
  166.  
  167.         /* Wait for handshake signal. */
  168.  
  169.     Wait(SIG_SHAKE);
  170.  
  171.         /* Process creation failed. */
  172.  
  173.     if(!ExecuteProc)
  174.     {
  175.         CloseAll();
  176.  
  177.         Forbid();
  178.  
  179.         MSeg -> Child = NULL;
  180.         Signal(MSeg -> Father,MSeg -> RingBack);
  181.  
  182.         goto Quit;
  183.     }
  184.  
  185.         /* Now we are truly running. */
  186.  
  187.     Signal(MSeg -> Father,MSeg -> RingBack);
  188.  
  189.     MSeg -> Father = NULL;
  190.  
  191.         /* Re-init the MsgPort flags. */
  192.  
  193.     MSeg -> Port . mp_Flags        = PA_SIGNAL;
  194.     MSeg -> Port . mp_SigBit    = SigBit;
  195.     MSeg -> Port . mp_SigTask    = MSeg -> Child;
  196.  
  197.         /* Wait until somebody kicks us out. */
  198.  
  199.     FOREVER
  200.     {
  201.         SignalSet = Wait(SIG_CLOSE | SIG_PORT);
  202.  
  203.             /* We are to shut down. */
  204.  
  205.         if(SignalSet & SIG_CLOSE)
  206.         {
  207.             if(ExecuteProc)
  208.             {
  209.                 Signal((struct Task *)ExecuteProc,SIG_CLOSE);
  210.  
  211.                 Wait(SIG_SHAKE);
  212.             }
  213.  
  214.             CloseAll();
  215.  
  216.             Forbid();
  217.  
  218.             Signal(MSeg -> Father,SIG_CLOSE);
  219.  
  220.             goto Quit;
  221.         }
  222.  
  223.             /* A message arrived at our home port. */
  224.  
  225.         if(SignalSet & SIG_PORT)
  226.         {
  227.                 /* Walk through the list of messages. */
  228.  
  229.             while(MacroMsg = (struct MacroMessage *)GetMsg(&MSeg -> Port))
  230.             {
  231.                     /* Execute a keyboard macro. */
  232.  
  233.                 if(MacroMsg -> mm_Type == MM_INPUT)
  234.                 {
  235.                     struct MacroKey *TempMacroKey = MacroMsg -> mm_MacroKey;
  236.  
  237.                     if(TempMacroKey)
  238.                     {
  239.                             /* Let the execute process run the command. */
  240.  
  241.                         if(TempMacroKey -> mk_Type == MK_COMMAND)
  242.                         {
  243.                             struct MacroMessage CommandMsg;
  244.  
  245.                             CommandMsg . mm_Type        = MM_EXECUTE;
  246.  
  247.                             CommandMsg . mm_FileName    = TempMacroKey -> mk_String;
  248.                             CommandMsg . mm_WindowName    = TempMacroKey -> mk_Window;
  249.  
  250.                             SendMacroMsg(&CommandMsg,ExecutePort);
  251.                         }
  252.  
  253.                             /* Build a keyboard macro. */
  254.  
  255.                         if(TempMacroKey -> mk_Type == MK_WORD)
  256.                         {
  257.                             ConsoleRequest -> io_Command    = CD_ASKDEFAULTKEYMAP;
  258.                             ConsoleRequest -> io_Length    = sizeof(struct KeyMap);
  259.                             ConsoleRequest -> io_Data    = (APTR)MSeg -> DefaultKeyMap;
  260.                             ConsoleRequest -> io_Flags    = IOF_QUICK;
  261.  
  262.                             DoIO(ConsoleRequest);
  263.  
  264.                             InputRequestBlock -> io_Command    = IND_WRITEEVENT;
  265.                             InputRequestBlock -> io_Data    = (APTR)FakeInputEvent;
  266.                             InputRequestBlock -> io_Length    = sizeof(struct InputEvent);
  267.  
  268.                             for(i = 0 ; i < strlen(TempMacroKey -> mk_String) ; i++)
  269.                             {
  270.                                 if(KeyInvert(TempMacroKey -> mk_String[i],FakeInputEvent,MSeg -> DefaultKeyMap,6))
  271.                                 {
  272.                                     FakeInputEvent -> ie_NextEvent    = NULL;
  273.                                     FakeInputEvent -> ie_Class    = IECLASS_RAWKEY;
  274.                                     FakeInputEvent -> ie_SubClass    = KM_SUBCLASS;
  275.  
  276.                                     FakeInputEvent -> ie_Qualifier |= IEQUALIFIER_RELATIVEMOUSE;
  277.  
  278.                                     TimeRequest -> tr_node . io_Command = TR_GETSYSTIME;
  279.  
  280.                                     DoIO(TimeRequest);
  281.  
  282.                                     FakeInputEvent -> ie_TimeStamp = TimeRequest -> tr_time;
  283.  
  284.                                     DoIO(InputRequestBlock);
  285.  
  286.                                     if(MSeg -> Delay)
  287.                                     {
  288.                                         TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  289.                                         TimeRequest -> tr_time . tv_secs    = 0;
  290.                                         TimeRequest -> tr_time . tv_micro    = MSeg -> Delay;
  291.  
  292.                                         DoIO(TimeRequest);
  293.                                     }
  294.                                 }
  295.                             }
  296.                         }
  297.                     }
  298.                 }
  299.  
  300.                 DeleteMacroMsg(MacroMsg);
  301.             }
  302.         }
  303.     }
  304.  
  305. Quit:    ;
  306. }
  307.  
  308.     /* UStrCmp():
  309.      *
  310.      *    strcmp function which ignores case and allows to
  311.      *    abbreviate the name of the source string to match
  312.      *    against the destination string.
  313.      */
  314.  
  315. BYTE
  316. UStrCmp(UBYTE *a,UBYTE *b)
  317. {
  318.     SHORT i;
  319.  
  320.     for(i = 0 ; i < strlen(a) ; i++)
  321.         if(ToUpper(a[i]) != ToUpper(b[i]))
  322.             return(1);
  323.  
  324.     return(0);
  325. }
  326.  
  327.     /* CreateFuncProc():
  328.      *
  329.      *    Create an independent process from a 'C' routine.
  330.      */
  331.  
  332. struct Process *
  333. CreateFuncProc(UBYTE *Name,LONG Priority,APTR InitCode,ULONG StackSize)
  334. {
  335.     struct Process *ChildProc = NULL;
  336.  
  337.     struct FakeSeg
  338.     {
  339.         BPTR    NextSeg;
  340.  
  341.         WORD    FirstCode;
  342.         APTR    RealCode;
  343.     } *FakeSeg;
  344.  
  345.     if(FakeSeg = (struct FakeSeg *)AllocMem(sizeof(struct FakeSeg),MEMF_PUBLIC | MEMF_CLEAR))
  346.     {
  347.         struct MsgPort *ChildPort;
  348.  
  349.         FakeSeg -> FirstCode    = 0x4EF9;
  350.         FakeSeg -> RealCode    = InitCode;
  351.  
  352.         if(ChildPort = (struct MsgPort *)CreateProc(Name,Priority,MKBADDR(FakeSeg),StackSize))
  353.             ChildProc = (struct Process *)ChildPort -> mp_SigTask;
  354.  
  355.         Delay(TICKS_PER_SECOND);
  356.  
  357.         FreeMem(FakeSeg,sizeof(struct FakeSeg));
  358.     }
  359.  
  360.     return(ChildProc);
  361. }
  362.  
  363.     /* FreeString(Byte):
  364.      *
  365.      *    Frees the memory occupied by the contents of a BSTR.
  366.      */
  367.  
  368. VOID
  369. FreeString(BPTR Byte)
  370. {
  371.     LONG *Ptr = (LONG *)BADDR(Byte);
  372.  
  373.     FreeMem(Ptr - 1,Ptr[-1]);
  374. }
  375.  
  376.     /* CreateBSTR(s):
  377.      *
  378.      *    Allocates enough memory to hold the contents of
  379.      *    a given string and makes it a BSTR.
  380.      */
  381.  
  382. BPTR
  383. CreateBSTR(UBYTE *s)
  384. {
  385.     LONG     BlockLength;
  386.     SHORT     Length;
  387.     UBYTE    *Byte;
  388.  
  389.     Length = strlen(s);
  390.  
  391.     BlockLength = (Length + 8) & ~3;
  392.  
  393.     if(!(Byte = (UBYTE *)AllocMem(BlockLength,MEMF_PUBLIC | MEMF_CLEAR)))
  394.         return(NULL);
  395.  
  396.     *(LONG *)Byte = BlockLength;
  397.  
  398.     Byte[4] = Length;
  399.     strncpy(Byte + 5,s,Length);
  400.  
  401.     return(MKBADDR(Byte + 4));
  402. }
  403.  
  404.     /* CopyPath():
  405.      *
  406.      *    Builds a fake pathlist inherited from any valid
  407.      *    CLI process or Workbench.
  408.      */
  409.  
  410. BPTR
  411. CopyPath()
  412. {
  413.     BPTR                *Next1,*Next2,*Last,NewPath = NULL;
  414.     struct Process            *Father;
  415.     struct CommandLineInterface    *CLI;
  416.  
  417.     Last = &NewPath;
  418.  
  419.         /* If using ARP this will also give us a valid
  420.          * pathlist.
  421.          */
  422.  
  423.     if(!(Father = (struct Process *)FindTask("Workbench")))
  424.         if(!(Father = (struct Process *)FindTask("ARP Shell Process")))
  425.             if(!(Father = (struct Process *)FindTask("New CLI")))
  426.                 if(!(Father = (struct Process *)FindTask("Initial CLI")))
  427.                     return(NULL);
  428.  
  429.     if(CLI = (struct CommandLineInterface *)BADDR(Father -> pr_CLI))
  430.     {
  431.         for(Next1 = (BPTR *)BADDR(CLI -> cli_CommandDir) ; Next1 ; Next1 = (BPTR *)BADDR(*Next1))
  432.         {
  433.             if(!(Next2 = (BPTR *)AllocMem(2 * sizeof(BPTR),MEMF_PUBLIC | MEMF_CLEAR)))
  434.                 break;
  435.  
  436.             *Last = MKBADDR(Next2);
  437.              Last = Next2;
  438.  
  439.             Next2[1] = (BPTR)DupLock(Next1[1]);
  440.             Next2[0] = NULL;
  441.         }
  442.     }
  443.  
  444.     return(NewPath);
  445. }
  446.  
  447.     /* FakeCLI():
  448.      *
  449.      *    Creates a fake CLI structure for our process. This
  450.      *    includes pathlist, currentdir, prompt and stack.
  451.      */
  452.  
  453. VOID
  454. FakeCLI()
  455. {
  456.     struct Process            *MyProcess = (struct Process *)SysBase -> ThisTask;
  457.     struct CommandLineInterface    *CLI;
  458.  
  459.     if(CLI = (struct CommandLineInterface *)AllocMem(sizeof(struct CommandLineInterface),MEMF_PUBLIC | MEMF_CLEAR))
  460.     {
  461.         MyProcess -> pr_CLI = MKBADDR(CLI);
  462.  
  463.         CLI -> cli_SetName    = CreateBSTR("SYS:");
  464.         CLI -> cli_Prompt    = CreateBSTR("%N> ");
  465.         CLI -> cli_DefaultStack    = 4000;
  466.  
  467.         CurrentDir(Lock("SYS:",ACCESS_READ));
  468.  
  469.         CLI -> cli_CommandDir    = CopyPath();
  470.     }
  471. }
  472.  
  473.     /* ClearPath(InitPath):
  474.      *
  475.      *    Frees the contents of our fake pathlist.
  476.      */
  477.  
  478. VOID
  479. ClearPath(BPTR InitPath)
  480. {
  481.     BPTR *Next,*Path;
  482.  
  483.     for(Path = (BPTR *)BADDR(InitPath) ; Path ; Path = Next)
  484.     {
  485.         Next = (BPTR *)BADDR(Path[0]);
  486.  
  487.         if(Path[1])
  488.             UnLock(Path[1]);
  489.  
  490.         FreeMem(Path,2 * sizeof(BPTR));
  491.     }
  492. }
  493.  
  494.     /* StopFakery():
  495.      *
  496.      *    Removes the contents of our fake CLI structure.
  497.      */
  498.  
  499. VOID
  500. StopFakery()
  501. {
  502.     struct CommandLineInterface    *CLI;
  503.     struct Process            *MyProcess;
  504.     BPTR                 MyCD;
  505.  
  506.     MyProcess = (struct Process *)SysBase -> ThisTask;
  507.  
  508.     if(CLI = (struct CommandLineInterface *)BADDR(MyProcess -> pr_CLI))
  509.     {
  510.         if(MyCD = (BPTR)CurrentDir(NULL))
  511.             UnLock(MyCD);
  512.  
  513.         FreeString(CLI -> cli_SetName);
  514.         FreeString(CLI -> cli_Prompt);
  515.  
  516.         ClearPath(CLI -> cli_CommandDir);
  517.  
  518.         MyProcess -> pr_CLI = NULL;
  519.  
  520.         FreeMem(CLI,sizeof(struct CommandLineInterface));
  521.     }
  522. }
  523.  
  524.     /* DeleteMacroMsg(scm_Msg):
  525.      *
  526.      *    Remove a message from memory.
  527.      */
  528.  
  529. VOID *
  530. DeleteMacroMsg(struct MacroMessage *scm_Msg)
  531. {
  532.     if(scm_Msg && scm_Msg -> mm_Message . mn_Node . ln_Name == (UBYTE *)scm_Msg)
  533.         FreeRem(scm_Msg);
  534.  
  535.     return(NULL);
  536. }
  537.  
  538.     /* Executor():
  539.      *
  540.      *    This is the dummy process to execute programs.
  541.      */
  542.  
  543. VOID __saveds
  544. Executor()
  545. {
  546.     ULONG             SignalSet;
  547.     BPTR             NIL;
  548.     struct MacroMessage    *ExecuteMsg;
  549.     struct Window        *TheWindow;
  550.     UBYTE             TempLine[300];
  551.  
  552.     struct Process        *ThatsMe;
  553.  
  554.     BYTE             Activate;
  555.  
  556.     ThatsMe = (struct Process *)SysBase -> ThisTask;
  557.  
  558.         /* These are inherited from the father process,
  559.          * we had better cleared them out.
  560.          */
  561.  
  562.     ThatsMe -> pr_WindowPtr = (APTR)-1;
  563.  
  564.         /* Try to allocate a port (we can't use our builtin
  565.          * DOS port since we are actually calling DOS
  566.          * routines which may mix up the messages coming
  567.          * in).
  568.          */
  569.  
  570.     if(!(ExecutePort = (struct MsgPort *)CreatePort(NULL,0)))
  571.     {
  572.         Forbid();
  573.  
  574.         ExecuteProc = NULL;
  575.  
  576.         Signal(MSeg -> Child,SIG_SHAKE);
  577.  
  578.         goto Quit;
  579.     }
  580.  
  581.         /* Open the NULL-Handler. */
  582.  
  583.     if(!(NIL = Open("NULL:",MODE_NEWFILE)))
  584.     {
  585.         Forbid();
  586.  
  587.         ExecuteProc = NULL;
  588.  
  589.         Signal(MSeg -> Child,SIG_SHAKE);
  590.         DeletePort(ExecutePort);
  591.  
  592.         goto Quit;
  593.     }
  594.  
  595.         /* Pretend to be a CLI. */
  596.  
  597.     FakeCLI();
  598.  
  599.         /* This path leads nowhere. */
  600.  
  601.     ThatsMe -> pr_CIS        = NIL;
  602.     ThatsMe -> pr_COS        = NIL;
  603.  
  604.     ThatsMe -> pr_ConsoleTask    = (APTR)DeviceProc("NULL:");
  605.  
  606.         /* We're on the scene now. */
  607.  
  608.     Signal(MSeg -> Child,SIG_SHAKE);
  609.  
  610.     FOREVER
  611.     {
  612.         SignalSet = Wait(SIG_CLOSE | (1 << ExecutePort -> mp_SigBit));
  613.  
  614.             /* Shut down? */
  615.  
  616.         if(SignalSet & SIG_CLOSE)
  617.         {
  618.             StopFakery();
  619.             Close(NIL);
  620.             DeletePort(ExecutePort);
  621.  
  622.             ExecuteProc = NULL;
  623.  
  624.             Forbid();
  625.  
  626.             Signal(MSeg -> Child,SIG_SHAKE);
  627.  
  628.             goto Quit;
  629.         }
  630.  
  631.             /* Execute a command? */
  632.  
  633.         while(ExecuteMsg = (struct MacroMessage *)GetMsg(ExecutePort))
  634.         {
  635.             TheWindow    = NULL;
  636.             Activate    = TRUE;
  637.  
  638.                 /* Try to find a matching window title. */
  639.  
  640.             if(ExecuteMsg -> mm_WindowName)
  641.             {
  642.                 ULONG         IntuiLock;
  643.  
  644.                 struct Screen    *ExScreen;
  645.                 struct Window    *ExWindow;
  646.  
  647.                 IntuiLock = LockIBase(NULL);
  648.  
  649.                 if(UStrCmp(ExecuteMsg -> mm_WindowName,IntuitionBase -> ActiveWindow -> Title))
  650.                 {
  651.                     ExScreen = IntuitionBase -> FirstScreen;
  652.  
  653.                     do
  654.                     {
  655.                         ExWindow = ExScreen -> FirstWindow;
  656.  
  657.                         do
  658.                         {
  659.                             if(!UStrCmp(ExecuteMsg -> mm_WindowName,ExWindow -> Title))
  660.                             {
  661.                                 TheWindow = ExWindow;
  662.                                 break;
  663.                             }
  664.                         }
  665.                         while((ExWindow = ExWindow -> NextWindow) && !TheWindow);
  666.                     }
  667.                     while((ExScreen = ExScreen -> NextScreen) && !TheWindow);
  668.                 }
  669.                 else
  670.                 {
  671.                     TheWindow = IntuitionBase -> ActiveWindow;
  672.                     Activate = FALSE;
  673.                 }
  674.  
  675.                 UnlockIBase(IntuiLock);
  676.             }
  677.  
  678.             if(!TheWindow)
  679.             {
  680.                     /* No chance, execute the command. */
  681.  
  682.                 strcpy(TempLine,"C:Run <NULL: >NULL: ");
  683.                 strcat(TempLine,ExecuteMsg -> mm_FileName);
  684.  
  685.                 Execute(TempLine,NULL,NIL);
  686.             }
  687.  
  688.             DeleteMacroMsg(ExecuteMsg);
  689.  
  690.                 /* Found a window? Bring it to the front. */
  691.  
  692.             if(TheWindow)
  693.             {
  694.                 LockLayers(TheWindow -> RPort -> Layer -> LayerInfo);
  695.  
  696.                 WindowToFront(TheWindow);
  697.  
  698.                 UnlockLayers(TheWindow -> RPort -> Layer -> LayerInfo);
  699.  
  700.                 ScreenToFront(TheWindow -> WScreen);
  701.  
  702.                 if(Activate)
  703.                     ActivateWindow(TheWindow);
  704.             }
  705.         }
  706.     }
  707.  
  708.         /* Finished, fall through. */
  709.  
  710. Quit:    ;
  711. }
  712.  
  713.     /* FindMacroKey(Code,Qualifier):
  714.      *
  715.      *    Find a macro key entry in the linked list of
  716.      *    macro key structures.
  717.      */
  718.  
  719. struct MacroKey *
  720. FindMacroKey(LONG Code,LONG Qualifier)
  721. {
  722.     SHORT i;
  723.  
  724.     if(MSeg -> MacroList)
  725.     {
  726.         ObtainSemaphore(&MSeg -> MacroSemaphore);
  727.  
  728.         for(i = 0 ; i < MSeg -> NumMacros ; i++)
  729.         {
  730.             if(MSeg -> MacroList[i] -> mk_CommandKey == Code && (Qualifier & ~HIDEFLAGS) == MSeg -> MacroList[i] -> mk_CommandQualifier)
  731.             {
  732.                 ReleaseSemaphore(&MSeg -> MacroSemaphore);
  733.  
  734.                 return(MSeg -> MacroList[i]);
  735.             }
  736.         }
  737.  
  738.         ReleaseSemaphore(&MSeg -> MacroSemaphore);
  739.     }
  740.  
  741.     return(NULL);
  742. }
  743.  
  744.     /* EventHandler(Event):
  745.      *
  746.      *    The input event handler.
  747.      */
  748.  
  749. struct InputEvent * __asm __saveds
  750. EventHandler(register __a0 struct InputEvent *Event)
  751. {
  752.     struct MacroKey        *HandlerKey;
  753.     struct InputEvent    *ChainEvent;
  754.  
  755.     for(ChainEvent = Event ; ChainEvent ; ChainEvent = ChainEvent -> ie_NextEvent)
  756.     {
  757.         if(ChainEvent -> ie_Class == IECLASS_RAWKEY && !(ChainEvent -> ie_Code & IECODE_UP_PREFIX) && ChainEvent -> ie_SubClass != KM_SUBCLASS)
  758.         {
  759.             if(HandlerKey = (struct MacroKey *)FindMacroKey(ChainEvent -> ie_Code,ChainEvent -> ie_Qualifier))
  760.             {
  761.                 struct MacroMessage HandlerMsg;
  762.  
  763.                 HandlerMsg . mm_Type        = MM_INPUT;
  764.                 HandlerMsg . mm_MacroKey    = HandlerKey;
  765.  
  766.                 SendMacroMsg(&HandlerMsg,&MSeg -> Port);
  767.  
  768.                 ChainEvent -> ie_Class = IECLASS_NULL;
  769.             }
  770.         }
  771.     }
  772.  
  773.     return(Event);
  774. }
  775.  
  776.     /* OpenAll():
  777.      *
  778.      *    Initialize the input event handler.
  779.      */
  780.  
  781. BYTE
  782. OpenAll()
  783. {
  784.     if(!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",33)))
  785.         return(FALSE);
  786.  
  787.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",33)))
  788.         return(FALSE);
  789.  
  790.     if(!(LayersBase = (struct Library *)OpenLibrary("layers.library",33)))
  791.         return(FALSE);
  792.  
  793.     if(!(InputDevPort = (struct MsgPort *)CreatePort(NULL,0)))
  794.         return(FALSE);
  795.  
  796.     if(!(InputRequestBlock = (struct IOStdReq *)CreateStdIO(InputDevPort)))
  797.         return(FALSE);
  798.  
  799.     if(OpenDevice("input.device",0,(struct IORequest *)InputRequestBlock,0))
  800.         return(FALSE);
  801.  
  802.     if(!(InputHandler = (struct Interrupt *)AllocMem(sizeof(struct Interrupt),MEMF_PUBLIC | MEMF_CLEAR)))
  803.         return(FALSE);
  804.  
  805.     if(!(ConsolePort = (struct MsgPort *)CreatePort(NULL,0)))
  806.         return(FALSE);
  807.  
  808.     if(!(ConsoleRequest = (struct IOStdReq *)CreateStdIO(ConsolePort)))
  809.         return(FALSE);
  810.  
  811.     if(OpenDevice("console.device",CONU_LIBRARY,ConsoleRequest,0))
  812.         return(FALSE);
  813.  
  814.     if(!(TimePort = (struct MsgPort *)CreatePort(NULL,0)))
  815.         return(FALSE);
  816.  
  817.     if(!(TimeRequest = (struct timerequest *)CreateExtIO(TimePort,sizeof(struct timerequest))))
  818.         return(FALSE);
  819.  
  820.     if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0))
  821.         return(FALSE);
  822.  
  823.     if(!(FakeInputEvent = (struct InputEvent *)AllocMem(sizeof(struct InputEvent),MEMF_PUBLIC | MEMF_CLEAR)))
  824.         return(FALSE);
  825.  
  826.     if((SigBit = AllocSignal(-1)) == -1)
  827.         return(FALSE);
  828.  
  829.     InputHandler -> is_Code            = (APTR)EventHandler;
  830.     InputHandler -> is_Node . ln_Pri    = MSeg -> Pri;
  831.     InputHandler -> is_Node . ln_Name    = "KeyMacro-Handler";
  832.  
  833.     InputRequestBlock -> io_Command        = IND_ADDHANDLER;
  834.     InputRequestBlock -> io_Data        = (APTR)InputHandler;
  835.  
  836.     if(DoIO(InputRequestBlock))
  837.         return(FALSE);
  838.  
  839.     ConsoleRequest -> io_Command    = CD_ASKDEFAULTKEYMAP;
  840.     ConsoleRequest -> io_Length    = sizeof(struct KeyMap);
  841.     ConsoleRequest -> io_Data    = (APTR)MSeg -> DefaultKeyMap;
  842.     ConsoleRequest -> io_Flags    = IOF_QUICK;
  843.  
  844.     if(DoIO(ConsoleRequest))
  845.         return(FALSE);
  846.  
  847.     return(TRUE);
  848. }
  849.  
  850.     /* CloseAll():
  851.      *
  852.      *    Remove the input event handler.
  853.      */
  854.  
  855. VOID
  856. CloseAll()
  857. {
  858.     if(InputRequestBlock)
  859.     {
  860.         if(InputRequestBlock -> io_Device)
  861.         {
  862.             if(InputHandler)
  863.             {
  864.                 InputRequestBlock -> io_Command    = IND_REMHANDLER;
  865.                 InputRequestBlock -> io_Data    = (APTR)InputHandler;
  866.  
  867.                 DoIO(InputRequestBlock);
  868.             }
  869.  
  870.             CloseDevice(InputRequestBlock);
  871.         }
  872.  
  873.         DeleteStdIO(InputRequestBlock);
  874.     }
  875.  
  876.     if(TimeRequest)
  877.     {
  878.         if(TimeRequest -> tr_node . io_Device)
  879.             CloseDevice(TimeRequest);
  880.  
  881.         DeleteExtIO(TimeRequest);
  882.     }
  883.  
  884.     if(TimePort)
  885.         DeletePort(TimePort);
  886.  
  887.     if(ConsoleRequest)
  888.     {
  889.         if(ConsoleRequest -> io_Device)
  890.             CloseDevice(ConsoleRequest);
  891.  
  892.         DeleteStdIO(ConsoleRequest);
  893.     }
  894.  
  895.     if(FakeInputEvent)
  896.         FreeMem(FakeInputEvent,sizeof(struct InputEvent));
  897.  
  898.     if(InputHandler)
  899.         FreeMem(InputHandler,sizeof(struct Interrupt));
  900.  
  901.     if(InputDevPort)
  902.         DeletePort(InputDevPort);
  903.  
  904.     if(ConsolePort)
  905.         DeletePort(ConsolePort);
  906.  
  907.     if(SigBit != -1)
  908.         FreeSignal(SigBit);
  909.  
  910.     if(LayersBase)
  911.         CloseLibrary(LayersBase);
  912.  
  913.     if(IntuitionBase)
  914.         CloseLibrary(IntuitionBase);
  915.  
  916.     if(DOSBase)
  917.         CloseLibrary(DOSBase);
  918. }
  919.